<?php

namespace App\Console\Commands;

use App\Consts\CacheKeyConst;
use Illuminate\Support\Facades\Artisan;
use Illuminate\Support\Facades\Cache;

class ScheduleWorkCommand extends BaseCommand
{
    /**
     * The name and signature of the console command.
     *
     * @var string
     */
    protected $signature = 'schedule:work {--action=reload}';

    /**
     * The console command description.
     *
     * @var string
     */
    protected $description = 'Start a blocking schedule to run cron jobs.';

    /**
     * Create a new command instance.
     *
     * @return void
     */
    public function __construct()
    {
        parent::__construct();
    }

    /**
     * Execute the console command.
     *
     * @return mixed
     * @throws \Exception
     */
    public function handler()
    {
        $action = $this->option('action');
        if (method_exists(self::class, $action)) {
            return $this->$action();
        }
        return true;
    }

    /**
     * start cron
     * @return bool
     * @throws \Exception
     */
    public function start()
    {
        if (Cache::store('redis')->get(CacheKeyConst::BLOCKING_SCHEDULE_STATUS)) {
            return true;
        }
        $uid = uniqid();
        $info = "[SCHEDULE][WORK][START] - " . json_encode([
                'uid' => $uid,
            ]);
        $this->logger($info);
        Cache::store('redis')->put(CacheKeyConst::BLOCKING_SCHEDULE_STATUS, 1, 30 * 1440);
        $res = true;
        while (true) {
            if (getCacheByRetry(CacheKeyConst::BLOCKING_SCHEDULE_STATUS)) {
                Artisan::call('schedule:run');
            } else {
                return $res = false;
            }
            sleep(60);
        }
        $info = "[SCHEDULE][WORK][END] - " . json_encode([
                'result' => $res,
                'uid' => $uid,
            ]);
        $this->logger($info);
        return true;
    }

    /**
     * stop cron
     * @return bool|array
     */
    public function stop()
    {
        // clear blocking cache
        for ($i = 0; $i < 5; $i ++) {
            Cache::store('redis')->forget(CacheKeyConst::BLOCKING_SCHEDULE_STATUS);
            sleep(5);
        }
        // finished
        return true;
    }

    /**
     * reload cron
     * @return bool
     * @throws \Exception
     */
    public function reload()
    {
        $this->stop();
        // blocking with 10 s
        sleep(20);
        $this->start();
        return true;
    }

}
